package com.appengine.hotornot.ui.controller;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jdo.JDOOptimisticVerificationException;
import javax.jdo.PersistenceManager;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import com.appengine.hotornot.entity.VoitesEntity;
import com.appengine.hotornot.ui.model.CandidateModel;
import com.appengine.hotornot.utils.StringUtils;
import com.google.appengine.repackaged.com.google.common.base.StringUtil;
import com.google.appengine.repackaged.com.google.protobuf.ServiceException;


public class VoiteController extends AbstractUIController{
	private static final Logger log = Logger.getLogger(VoiteController.class
			.getName());
	/**
	 * 
	 */
	private static final long serialVersionUID = 210324091970540478L;
	private HttpSession session;
	
	private CandidateModel candidate0;
	private CandidateModel candidate1;

	public VoiteController(HttpServletRequest request) {
		super(request);	
	}

	@Override
	public void doJob() {
		log.entering(VoiteController.class.getName(), "doJob");			
		persist();
		try {
			initCandidates();
		} catch (Exception e) {
			log.log(Level.SEVERE,"Init candidates fail",e);
		} 
		log.exiting(VoiteController.class.getName(), "doJob");
		return;					
	}	
	
	/**
	 * Init candidates
	 * @throws IOException
	 * @throws ServiceException
	 */
	private void initCandidates() throws Exception
	{
		log.entering(VoiteController.class.getName(), "initCandidates");		
		final InputStream inputStream = getInputStream();
		final Document parse = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream);
		final NodeList entries = parse.getElementsByTagName("entry");
		long length = entries.getLength();		
		
		length--;
		final long index0=System.currentTimeMillis()%length;
		long index1;
		if(index0==0)
		{
			index1=length;
		}
		else
		{
			index1=index0-1;
		}
						
		int intValue0 = new Long(index0).intValue();
		candidate0 = createCandidate(entries.item(intValue0));
		session.setAttribute(CANDIDATE_0_ID,candidate0.getPhotoId());
		
		int intValue1 = new Long(index1).intValue();
		candidate1 = createCandidate(entries.item(intValue1));
		session.setAttribute(CANDIDATE_1_ID,candidate1.getPhotoId());
		
		log.exiting(VoiteController.class.getName(), "initCandidates");
	}	
	
	/**
	 * Persist voites
	 */
	private void persist()
	{
		log.entering(VoiteController.class.getName(), "persist");	
		final String command = request.getParameter(VOITE_CANDIDATE);
		
		if(StringUtil.isEmpty(command))
		{
			return;
		}
		
		String attribute=null;
		if("0".equalsIgnoreCase(command))
		{
			attribute = (String)session.getAttribute(CANDIDATE_0_ID);						
		}
		else if("1".equalsIgnoreCase(command))
		{
			attribute = (String)session.getAttribute(CANDIDATE_1_ID);
			
		}
		int count=UPDATES_COUNTS;
		while(count>=0 && !incrementCount(attribute))
		{
			count--;
		}
		log.exiting(VoiteController.class.getName(), "persist");	
	}
	
	/**
	 * Increment votes
	 * @param id
	 * @return
	 */
	private boolean incrementCount(String id)
	{
		log.entering(VoiteController.class.getName(), "incrementCount");	
		if(StringUtils.isEmpty(id))
		{
			log.entering(VoiteController.class.getName(), "incrementCount");
			return true;
		}
		final PersistenceManager pm = getPersistenceManager();
		try {			
			final String query = "select from "
				+ VoitesEntity.class.getName() + " where photoId=='"
				+ id+"'";
			final List<VoitesEntity> items = (List<VoitesEntity>) pm.newQuery(query).execute();
			VoitesEntity voitesEntity=null;
			if(items==null || items.size()<=0)
			{				
				voitesEntity=new VoitesEntity();
				voitesEntity.setPhotoId(id);
				voitesEntity.setVoites(new Long(0));
			}
			else
			{
				voitesEntity = items.get(0);
			}
			
			pm.currentTransaction().begin();						
			Long voites = voitesEntity.getVoites();
			voites++;
			voitesEntity.setVoites(voites);
			pm.makePersistent(voitesEntity);
			
			pm.currentTransaction().commit();
		} catch (JDOOptimisticVerificationException e) {
			log.exiting(VoiteController.class.getName(), "incrementCount");	
			return false;
		}
		finally
		{
			if (pm.currentTransaction().isActive()) {
	            pm.currentTransaction().rollback();
	        }			
		}
		log.exiting(VoiteController.class.getName(), "incrementCount");	
		return true;		
	}
	
	public CandidateModel getCandidate0() {
		return candidate0;
	}

	public CandidateModel getCandidate1() {
		return candidate1;
	}

	public void setSession(HttpSession session) {
		this.session = session;
	}
	
}
